﻿/**
 * @file DriverManager.h
 * @brief 设备驱动管理器类定义 - 现代C++/Qt风格重构版本
 * @details 提供COM端口设备的枚举、配置、状态管理和友好名称更新功能
 * @author 重构版本
 * @date 2024
 */

#ifndef DRIVERMANAGER_H
#define DRIVERMANAGER_H

#include <QObject>
#include <QString>
#include <QStringList>
#include <QList>
#include <QMutex>
#include <QWidget>
#include <QDebug>
#include <functional>
#include <memory>
#include "DriverStruct.h"

// 前向声明，减少头文件依赖
class QTimer;

// Windows API 前向声明
typedef void* HDEVINFO;
struct _SP_DEVINFO_DATA;
typedef struct _SP_DEVINFO_DATA* PSP_DEVINFO_DATA;

/**
 * @brief 设备状态枚举
 * @details 定义设备的各种运行状态
 */
enum class DeviceState {
    Unknown,    ///< 未知状态 - 无法确定设备状态
    Active,     ///< 活动状态 - 设备正常工作
    Inactive,   ///< 非活动状态 - 设备存在但未启动
    Disabled,   ///< 禁用状态 - 设备被手动禁用
    Removed     ///< 移除状态 - 设备已被移除
};

/**
 * @brief 消息类型枚举
 * @details 定义不同类型的用户消息
 */
enum class MessageType {
    Information,    ///< 信息消息 - 一般性通知
    Warning,        ///< 警告消息 - 需要注意的情况
    Error,          ///< 错误消息 - 发生了错误
    Question        ///< 询问消息 - 需要用户确认
};

/**
 * @brief 操作结果枚举
 * @details 定义各种操作的执行结果
 */
enum class OperationResult {
    Success,        ///< 操作成功完成
    Failed,         ///< 操作失败
    Cancelled,      ///< 操作被用户取消
    Timeout,        ///< 操作超时
    InvalidParam    ///< 参数无效
};

/**
 * @brief 设备类型枚举
 * @details 定义不同类型的设备
 */
enum class DeviceType {
    Unknown,        ///< 未知设备类型
    BusDevice,      ///< 总线设备 - 管理子设备的总线控制器
    VirtualPort,    ///< 虚拟端口 - 软件模拟的串口
    VirtualPortCst, ///< 自定义虚拟端口 - 软件模拟的串口
};

/**
 * @brief 设备信息结构体
 * @details 包含设备的完整信息
 */
struct DeviceInfo {
    QString hardwareId;     ///< 硬件ID - 设备的唯一标识符
    QString friendlyName;   ///< 友好名称 - 用户可读的设备名称
    QString portName;       ///< 端口名称 - COM端口名称（如果适用）
    QString portPair;       ///< 所属串口对 - 虚拟端口设备所属串口对
    DeviceState state;      ///< 设备状态 - 当前运行状态
    DeviceType type;        ///< 设备类型 - 设备的分类类型
    bool isValid;           ///< 有效性标志 - 设备信息是否有效
    
    /**
     * @brief 默认构造函数
     */
    DeviceInfo() : state(DeviceState::Unknown), type(DeviceType::Unknown), isValid(false) {}

    /**
     * @brief 打印设备信息
     * @details 用于调试和日志记录，输出设备的所有属性
     */
    void print() const {
        qDebug() << QString("[ HardwareID=%1, FriendlyName=%2, PortName=%3, PortPair=%4, State=%5, Type=%6, IsValid=%7 ]")
                    .arg(hardwareId)
                    .arg(friendlyName)
                    .arg(portName)
                    .arg(portPair)
                    .arg(static_cast<int>(state))
                    .arg(static_cast<int>(type))
                    .arg(isValid ? "true" : "false");
    }
};

/**
 * @brief 设备枚举回调函数类型
 * @details 用于设备枚举过程中的过滤和处理
 * @param hardwareId 设备硬件ID
 * @return 是否接受该设备
 */
using DeviceEnumCallback = std::function<bool(const QString& hardwareId)>;

struct PortPair;

/**
 * @brief 设备驱动管理器类
 * @details 现代C++/Qt风格的设备管理器，提供完整的设备管理功能
 * 
 * 主要功能：
 * - 设备枚举和发现
 * - 设备状态管理（启用/禁用/移除/重启）
 * - COM端口数据库同步
 * - 友好名称管理
 * - 端口名称验证
 * - 异步操作支持
 * 
 * 使用示例：
 * @code
 * DriverManager manager;
 * if (manager.initialize()) {
 *     auto devices = manager.getDeviceList();
 *     for (const auto& device : devices) {
 *         qDebug() << device.friendlyName << device.portName;
 *     }
 * }
 * @endcode
 */
class DriverManager : public QObject
{
    Q_OBJECT

public:
    /**
     * @brief 构造函数
     * @param parent 父对象指针，用于Qt对象树管理
     */
    explicit DriverManager(QObject* parent = nullptr);
    
    /**
     * @brief 析构函数
     * @details 自动清理所有资源和停止正在进行的操作
     */
    ~DriverManager();

    // === 核心管理功能 ===
    
    /**
     * @brief 初始化驱动管理器
     * @details 执行必要的初始化操作，包括设备枚举和数据库同步
     * @return 初始化是否成功
     * @note 必须在使用其他功能前调用此方法
     */
    bool initialize();
    
    /**
     * @brief 清理资源
     * @details 停止所有操作并释放占用的资源
     */
    void cleanup();

    /**
     * @brief 创建虚拟串口对
     * @return
     */
    bool createPortPair();

    /**
     * @brief 删除虚拟串口对
     * @return
     */
    bool removePortPair(int num);

    // === 设备枚举功能 ===
    
    /**
     * @brief 枚举设备
     * @param filter 设备过滤器函数
     * @param deviceProps 设备属性参考
     * @return 找到的设备数量
     */
    void enumerateDevices(DeviceEnumCallback filter, const DeviceProperties& deviceProps, bool *rebootRequired);
    
    /**
     * @brief 获取设备列表
     * @details 返回当前已发现的所有设备信息
     * @return 设备信息列表的副本
     * @note 线程安全的方法
     */
    const QList<DeviceInfo>& getDeviceList() const;
    
    /**
     * @brief 获取设备数量
     * @details 返回当前管理的设备总数
     * @return 设备数量
     * @note 线程安全的方法
     */
    int getDeviceCount() const;
    
    /**
     * @brief 检查是否已初始化
     * @details 检查管理器是否已成功初始化
     * @return 是否已初始化
     * @note 线程安全的方法
     */
    bool isInitialized() const;

    // === 设备状态控制 ===
    
    /**
     * @brief 启用设备
     * @param deviceInfo 要启用的设备信息
     * @return 操作结果
     */
    OperationResult enableDevice(const DeviceInfo& deviceInfo);
    
    /**
     * @brief 禁用设备
     * @param deviceInfo 要禁用的设备信息
     * @return 操作结果
     */
    OperationResult disableDevice(const DeviceInfo& deviceInfo);
    
    /**
     * @brief 移除设备
     * @param deviceInfo 要移除的设备信息
     * @return 操作结果
     */
    OperationResult removeDevice(const DeviceInfo& deviceInfo);
    
    /**
     * @brief 重启设备
     * @param deviceInfo 要重启的设备信息
     * @return 操作结果
     */
    OperationResult restartDevice(const DeviceInfo& deviceInfo);

    // === 数据库和配置管理 ===
    
    /**
     * @brief 同步COM端口数据库
     * @details 将当前设备状态与系统COM端口数据库同步
     * @return 操作结果
     */
    OperationResult synchronizeComDatabase();

    /**
     * @brief Inf文件自检
     * @return 操作结果
     */
    OperationResult selfCheckInfFileList();

    /**
     * @brief 检查服务类是否已安装
     * @return 是/否
     */
    static bool isServiceClassInstalled();

    // === 实用工具方法 ===
    
    /**
     * @brief 验证端口名称有效性
     * @param portName 要验证的端口名称
     * @return 端口名称是否有效
     * @note 检查端口名称格式、长度和可用性
     */
    static bool isValidPortName(const QString& portName);
    
    /**
     * @brief 显示消息框
     * @param type 消息类型
     * @param message 消息内容
     * @return 用户选择结果
     */
    int showMessage(MessageType type, const QString& message);
    
    /**
     * @brief 等待安装事件完成
     * @param timeLimit 时间限制（毫秒）
     * @param repeat 是否重复等待
     * @return 是否成功等待
     */
    static bool waitForInstallEvents(int timeLimit, bool repeat = false);

    /**
     * @brief 获取bus设备管理的端口对名称
     * @param portNum bus设备的端口号
     * @return 端口对名称（格式：CNCA{portNum}-CNCB{portNum}）
     */
    static const QStringList getBusPortPairName(int portNum);

    /**
     * @brief 根据PortName检查设备是否为COM端口设备
     * @param portName 端口名
     * @return 是否为COM端口设备
     */
    static bool isComPortDeviceFromPortName(const QString& portName);

signals:
    /**
     * @brief 初始化完成信号
     * @param success 初始化是否成功
     */
    void initializationCompleted();
    
    /**
     * @brief 发现设备信号
     * @param deviceInfo 发现的设备信息
     */
    void deviceFound(const DeviceInfo& deviceInfo);
    
    /**
     * @brief 设备状态改变信号
     * @param deviceInfo 设备信息
     * @param newState 新状态
     */
    void deviceStateChanged(const DeviceInfo& deviceInfo, DeviceState newState);
    
    /**
     * @brief 设备移除信号
     * @param deviceInfo 被移除的设备信息
     */
    void deviceRemoved(const DeviceInfo& deviceInfo);
    
    /**
     * @brief COM数据库同步完成信号
     */
    void comDatabaseSynchronized();

    /**
     * @brief 设备信息变动信号
     */
    void deviceChanged(bool isValid = true);

public slots:
    /**
     * @brief 刷新设备列表
     * @details 重新枚举设备并更新内部列表
     */
    void refreshDeviceList(bool init = false);

private slots:
    /**
     * @brief 定时器超时处理槽
     * @details 处理定期任务，如设备状态检查
     */
    void onTimerTimeout();

private:
    // === 内部辅助方法 ===
    
    /**
     * @brief 获取设备硬件ID
     * @param hDevInfo 设备信息句柄
     * @param pDevInfoData 设备信息数据指针
     * @return 硬件ID字符串
     */
    QString getDeviceHardwareId(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData);

    /**
     * @brief 获取设备全部硬件ID（REG_MULTI_SZ）
     * @param hDevInfo 设备信息句柄
     * @param pDevInfoData 设备信息数据指针
     * @return 硬件ID列表（主ID在前）
     */
    QStringList getDeviceHardwareIds(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData);

    /**
     * @brief 从端口名称获取硬件ID
     * @param portName 端口名称
     * @return 硬件ID列表（主ID在前）
     */
    QStringList getDeviceHardwareIdsFromPortName(const QString& portName);

    /**
     * @brief 根据端口号生成端口对标识
     * @param portNum 端口号
     * @return 端口对标识字符串
     */
    QString generatePortPairId(int portNum);
    
    /**
     * @brief 创建总线设备信息结构
     * @param hDevInfo 设备信息句柄
     * @param pDevInfoData 设备信息数据指针
     * @param deviceProps 设备属性
     * @return 设备信息结构
     */
    bool createBusDeviceInfo(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData,
                               const DeviceProperties& deviceProps, bool *rebootRequired);
    
    /**
     * @brief 创建子端口信息结构
     * @param portNum
     */
    bool createPortDeviceInfo(int portNum, bool *rebootRequired);

    /**
     * @brief 获取设备友好名称
     * @param hDevInfo 设备信息句柄
     * @param pDevInfoData 设备信息数据指针
     * @return 友好名称字符串
     */
    QString getDeviceFriendlyName(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData);
    
    /**
     * @brief 从端口名称获取设备友好名称
     * @param portName 端口名称
     * @return 设备友好名称
     */
    QString getDeviceFriendlyNameFromPortName(const QString& portName);

    /**
     * @brief 获取设备状态
     * @param hDevInfo 设备信息句柄
     * @param pDevInfoData 设备信息数据指针
     * @return 设备状态枚举值
     */
    DeviceState getDeviceState(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData);
    
    /**
     * @brief 从端口名获取设备状态
     * @param portName 端口名
     * @return 设备状态枚举值
     */
    DeviceState getDeviceStateFromPortName(const QString& portName);

    /**
     * @brief 获取设备端口名称
     * @param hDevInfo 设备信息句柄
     * @param pDevInfoData 设备信息数据指针
     * @return 端口名称字符串
     */
    QString getDevicePortName(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDevInfoData);
    
    /**
     * @brief 根据HwId检查设备是否为COM端口设备
     * @param hardwareId 硬件ID
     * @return 是否为COM端口设备
     */
    bool isComPortDeviceFromHwId(const QString& hardwareId);
    
    /**
     * @brief 判断设备类型
     * @param hardwareId 硬件ID
     * @param friendlyName 友好名称
     * @param portName 端口名称
     * @return 设备类型
     */
    DeviceType determineDeviceType(const QString& hardwareId, const QString& friendlyName, const QString& portName);
    
    /**
     * @brief 更改设备状态
     * @param deviceInfo 设备信息
     * @param enable 是否启用
     * @return 操作结果
     */
    OperationResult changeDeviceState(const DeviceInfo& deviceInfo, bool enable);
    
    /**
     * @brief 更新端口信息到数据库
     * @param portName 端口名称
     * @param friendlyName 友好名称
     */
    void updatePortInDatabase(const QString& portName, const QString& friendlyName);
    
    /**
     * @brief 获取主窗口指针
     * @return 主窗口指针，如果没有找到则返回nullptr
     */
    QWidget* getMainWindow();
    
    /**
     * @brief 比较设备列表变化并发出信号
     * @param oldList 旧设备列表
     * @param newList 新设备列表
     */
    void compareAndEmitChanges(const QList<DeviceInfo>& oldList, 
                              const QList<DeviceInfo>& newList);
    
    /**
     * @brief 比较两个设备是否为同一设备
     * @param device1 第一个设备
     * @param device2 第二个设备
     * @return 如果是同一设备返回true，否则返回false
     */
    bool isSameDevice(const DeviceInfo& device1, const DeviceInfo& device2) const;

private:
    // === 成员变量 ===
    
    /// @brief COM端口数据库初始化标志
    static bool s_comDbInitialized;
    
    /// @brief 定时器，用于定期任务
    std::unique_ptr<QTimer> m_timer;
    
    /// @brief 设备信息列表
    QList<DeviceInfo> m_deviceInfoList;

    /// @brief 初始化状态标志
    bool m_isInitialized;
    
    /// @brief 当前管理的设备数量
    int m_deviceCount;    
    
    /// @brief 刷新重入保护标记
    bool m_isRefreshing = false;
};

// Qt元类型声明，支持信号槽系统
Q_DECLARE_METATYPE(DeviceState)
Q_DECLARE_METATYPE(DeviceType)
Q_DECLARE_METATYPE(MessageType)
Q_DECLARE_METATYPE(OperationResult)
Q_DECLARE_METATYPE(DeviceInfo)

#endif // DRIVERMANAGER_H
